package  ru.mipt.board.net
import   java.net._
import   scala.xml._


/**
 * Created by IntelliJ IDEA.
 * User: IL
 * Date: 13.09.2010
/
/ * Time: 18:50:55
 * To change this template use File | Settings | File Templates.
 */
/**
 * represents board message
 */
//TODO change structure of username from string  to maybe some case class
case class BoardMessage(val ID: Long,val username: String,val text: String,val threadID: Long,
                        val parentID: Option[Long],val header: String){

    override  def toString ()= {ID.toString + username.toString + text.toString +
                                threadID.toString + parentID.getOrElse(0).toString  }

    def this() = this(0,"","",0,Some(0),"")

    override def equals(that: Any): Boolean = {
        if ( ! that.isInstanceOf[BoardMessage]) false
        else that.asInstanceOf[BoardMessage].ID == ID //its assumed that id is unique if it isnt we ara in deep shit
    }
}

/**
 * loads and parses single thread by id
 * usage <code>
 * val a = new  BoardLoader
 * val b = a parseThread 752465 </code>
 * @param none empty by default
 */
class BoardLoader(){

    private def load(ID: Long):Elem = {
        assert((ID > 0),"Board supports only positive message IDs")
        val content =
        try {
            val url = new  URL("http://board.rt.mipt.ru/?read=" + ID toString)
            val connection = url.openConnection
            val loader = XML.withSAXParser(new org.ccil.cowan.tagsoup.jaxp.SAXFactoryImpl().newSAXParser())
            loader.load(url)
        } catch{
            case _ => throw new IllegalArgumentException()
        }
        content
    }

    /**
     * @param  ID of core message in thread
     * @throw  IllegalArgumentException if ID is negative does nothing if message does not exist
     */
    def parseThread(threadID:Long)={      //TODO check behaivor when given not root meassage ID
        var content:List[BoardMessage] = List()
        load(threadID) \ "body" \ "div" filter (a => (a \ "@class" text) == ("w")) foreach (a => process(a \ "div",None))
        def process(div:NodeSeq,parentID:Option[Long]):Unit={
            val id = ( """\d+""".r findFirstIn  (div \ "@id" text) get ) toLong;
            content = parseMessage(parentID,id) :: content;
            for{
                nextdiv <- (div \ "div" )
            }{
                 process(nextdiv ,Option(id))
            }
        }
        def parseMessage(parentID:Option[Long],ID:Long)={
            val div = load(ID)  \ "body"   \ "div"
            var message: String  = ""
            var username: String = ""
            var header: String = ""
            for {
                node <- div
            }{
                if((node \ "@align" text) == ("CENTER") ){
                    username = node \ "a" text;
                    header = node \ "big" map (_.text) mkString ;
                }
                {if((node \ "@class" text) == ("body") )   message  = node text}
            }
            new BoardMessage(ID,username,message,threadID,parentID,header)
        }
        content
    }
}